<?php
/**
 * 
 * @file 3gplex/includes/flashvideo.inc
 * 
 * Flashvideo contrib module configuration API.
 */

require_once('./'. drupal_get_path('module', 'drupalplex') .'/includes/module.inc');

define("PFLV_NO_NODETYPE", "Can't configure flashvideo for unknown node type");
define("PFLV_INVALID_SETTINGS", "Can't configure flashvideo for node type %nodetype:
	No or invalid settings");

class plex_flashvideo_exception extends plex_exception
{
	function __construct($message, $nodetype)
	{
		$this->message = $message;
		$this->arguments = array('%nodetype'=>$nodetype);
	}
}

class plex_settings_exception extends plex_exception
{
	function __construct($message, $module, $setting, $value)
	{
		$this->message = $message;
		$this->arguments = array('%module'=>$module, '%setting'=>$setting, '%value'=>$value);
	}
}

define("PSET_UNKNOWN_SETTING", "There is no such setting as %setting for %module");
define("PSET_ABSENT_SETTING", "Please fill settings [%setting] for %module");
define("PSET_INVALID_BOOLEAN", "%module's setting %setting is boolean, %value given (please provide true or false)");
define("PSET_UNHANDLED_VALUE", "%module's setting %setting can't be assigned a %value");

class plex_vector
{
	protected $vector;
	
	
	function add_dimension($name, $default)
	{
		$this->vector[$name] = $default;
	}

	function __set($dimension, $coordinate)
	{
		if (!isset($this->vector[$dimension])) {
			throw new plex_settings_exception(PSET_UNKNOWN_SETTING, "flashvideo", $dimension, null);
		}
		$actual =& $this->vector[$dimension];

		if (is_array($actual) || is_object($actual)) {
			$actual = unserialize($coordinate);
		} elseif (is_bool($actual)) {
			$coordinate = strtolower(trim($coordinate));
			if ($coordinate === "true") $actual = true;
			elseif ($coordinate === "false") $actual = false;
			else throw new plex_settings_exception(PSET_INVALID_BOOLEAN, "flashvideo", $dimension, $coordinate);
		} elseif (is_float($actual)) {
			$actual = (float)$coordinate;
		} elseif (is_double($actual)) {
			$actual = (double)$coordinate;
		} elseif (is_int($actual)) {
			$actual = (int)$coordinate;
		} elseif (is_string($actual)) {
			$actual = $coordinate;
		} else {
			throw new plex_settings_exception(PSET_UNHANDLED_VALUE, "flashvideo", $dimension, gettype($coordinate));
		}
	}

	function __get($dimension)
	{
		return $this->vector[$dimension];
	}

	function __isset($dimension)
	{
		return isset($this->vector[$dimension]);
	}

	function project(array $string_vector)
	{
		$d = array_diff_key($this->vector, $string_vector);
		if (!empty($d)) {
			throw new plex_settings_exception(PSET_ABSENT_SETTING, "flashvideo", implode(', ', $d), null);
		}
		foreach ($string_vector as $dimension => $coordinate) {
			if (!isset($this->$dimension)) {
				continue;
			}
			$this->$dimension = $coordinate;
		}
	}

	function assign(array $string_vector)
	{
		$d = array_diff_key($this->vector, $string_vector);
		if (!empty($d)) {
			throw new plex_settings_exception(PSET_ABSENT_SETTING, "flashvideo", implode(', ', $d), null);
		}
		$d = array_diff_key($string_vector, $this->vector);
		if (!empty($d)) {
			throw new plex_settings_exception(PSET_UNKNOWN_SETTING, "flashvideo", implode(', ', $d), null);
		}
		foreach ($string_vector as $dimension => $coordinate) {
			$this->$dimension = $coordinate;
		}
	}
}

class plex_flashvideo_settings extends plex_vector
{
	function __construct()
	{
		$this->vector = array(
		'require'=>0,
		'disabletag'=>0,
		'status'=>1,
		'convert'=>1,
		'import'=>'video_import',
		'title'=>'Video Upload',
		'weight'=>-10,
		'mode'=>'window',
		'embed'=>0,
		'embedtext'=>'Embed:',
		'embedsize'=>40,
		'download'=>0,
		'downloadfile'=>0,
		'downloadtext'=>'',
		'attachment'=>0,
		'searchthumb'=>0,
		'searchvideo'=>0,
		'player'=>'Player.swf',
		'flashvars'=>'file=@video',
		'logo'=>'',
		'logolink'=>'',
		'intro'=>'',
		'outro'=>'',
		'introimg'=>'',
		'introthumb'=>1,
		'introtime'=>'3',
		'autostart'=>true,
		'repeattype'=>'list',
		'ffmpegphp'=>1,
		'cmd'=>"-i @input -f flv -acodec mp3 -ar 22050 -ab 64k -ac 1 @output",
		'thumbcmd'=>'-y -i @input -vframes 1 -ss @thumbtime -an -vcodec mjpeg -f rawvideo -s "@thumbsize" @output',
		'binpath'=>'/usr/bin/ffmpeg',
		'delete'=>0,
		'userootpath'=>0,
		'originaldir'=>'',
		'outputdir'=>'',
		'size'=>'450x337',
		'thumbsize'=>'130x100',
		'thumbtime'=>'00:00:20',
		'thumblink'=>'yes',
		'maxconvert'=>10,
		'maxfail'=>5,
		'logdata'=>1
		);
		
	}
}


/**
 * Flashvideo contrib module wrapper.
 * 
 */
class plex_flashvideo extends plex_module
{
	protected $requires = array( 'upload' );
	function get_description()
	{
		return "Configures and loads API for Drupal contrib flashvideo module:
		Convert to and display embedded flash video from uploaded videos";
	}
	/**
	 * A completely const $defaults array which can't be made const.
	 */
	protected function build_settings_xml($xml)
	{
		return (array)plex::simplexml2array($xml);
	}
	
	protected function build_nodetype_settings_xml($xml)
	{
		return (array)plex::simplexml2array($xml);
	}

	protected function validate_settings(&$settings)
	{
		foreach ($settings as $nodetype => $properties) {
			$this->validate_nodetype_settings($nodetype, $settings[$nodetype]);
		}
	}

	protected function validate_nodetype_settings($nodetype, &$settings)
	{
		if (!is_string($nodetype) || strlen($nodetype) < 1)
			throw new plex_exception(PFLV_NO_NODETYPE);
	}

	protected function apply_settings(&$settings)
	{
		foreach ($settings as $nodetype => $properties) {
			$this->apply_nodetype_settings($nodetype, $settings[$nodetype]);
		}
	}

	protected function apply_nodetype_settings($nodetype, &$settings)
	{
		foreach ($settings as $setting => $value) {
			variable_set("flashvideo_${nodetype}_${setting}", $value);
		}
		variable_set("flashvideo_${nodetype}_enable", 1);
	}

	/**
	 * Sets flashvideo configuration for given $node_type.
	 */
	function configure_nodetype($nodetype, $xmltree)
	{
		try {
			if (is_a($xmltree, 'SimpleXMLElement')) {
				$settings = $this->build_nodetype_settings_xml($xmltree);
			} else if (is_array($xmltree)) {
				$settings = $xmltree;
			} else {
				throw new plex_flashvideo_exception(PFLV_INVALID_SETTINGS, $nodetype);
			}
			$this->validate_nodetype_settings($settings);
			$this->apply_nodetype_settings($nodetype, $settings);
		} catch (plex_exception $err) {
			$err->display();
			return false;
		}
		return true;
	}

}
/**
 * @page plex_flashvideo_page Flashvideo contrib module configuration formats
 * 
 * @section plex_flashvideo_examples Full Configuration Samples
 * 
 * @subsection plex_flashvideo_node_type_example Node Type Flashvideo Settings Description
 * 
 * Node types definition files and functions permit to configure flashvideo
 * (if for them), please refer to node type @ref plex_node_examples.
 * 
 */
